package cate.common.util;

import cp.solution.util.time.TimeKit;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class TimeTool {
	private static final Logger logger = LoggerFactory.getLogger(TimeTool.class);

	private static ThreadLocal<SimpleDateFormat> df1ThreadLocal = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));

	private static ThreadLocal<SimpleDateFormat> df2ThreadLocal = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));


	public static SimpleDateFormat getDF1() {
		return df1ThreadLocal.get();
	}

	public static SimpleDateFormat getDF2() {
		return df2ThreadLocal.get();
	}

	private static final String ZERO_STR = "00:00:00";

	/**
	 * 根据基准时间计算时间戳
	 * @param baseTime
	 * @param noDay 第几天（如果是1就是当天）
	 * @return
	 */
	public static long calTimeStamp(long baseTime, int noDay){
		return calTimeStamp(baseTime,noDay,ZERO_STR);
	}


	/**
	 * 根据基准时间计算时间戳
	 *
	 * @param baseTime 基准时间
	 * @param noDay 第几天（如果是1就是当天）
	 * @param str 一天中的某一个时刻 如 12:00:00
	 */
	public static long calTimeStamp(long baseTime, int noDay, String str) {
		int distenceDay = noDay - 1;
		if (distenceDay < 0) {
			distenceDay = 0;
		}
		Calendar c = Calendar.getInstance();
		c.setTimeInMillis(baseTime);
		c.add(Calendar.DATE, distenceDay);
		try {
			if (StringUtils.isNotBlank(str)) {
				return getDF2().parse(getDF1().format(c.getTimeInMillis()) + " " + str).getTime();
			} else {
				return TimeTool.getZeroTimeStamp(c.getTimeInMillis());
			}
		} catch (Exception e) {
			logger.error("时间格式解析异常 baseTime={},noDay={},str={}", baseTime, noDay, str);
		}
		return 0L;
	}

	/**
	 * 解析时间
	 * @param str  yyyy-MM-dd HH:mm:ss
	 * @return
	 */
	public static long parseTime(String str) {
		try {
			if (StringUtils.isNotBlank(str)) {
				return getDF2().parse(str).getTime();
			}
		} catch (Exception e) {
			logger.error("时间格式解析异常{}", str);
		}
		return 0L;
	}


	/** 获取某一天零点的时间戳 */
	public static long getZeroTimeStamp(long time) {
		Calendar c = Calendar.getInstance();
		c.setTimeInMillis(time);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);
		return c.getTimeInMillis();
	}

	/** 获取两个日期之间相隔的天数 */
	public static int getDistanceDays(long start, long end) {
		long startZero = getZeroTimeStamp(start);
		long endZero = getZeroTimeStamp(end);
		long dif = endZero - startZero;
		long days = dif / (1000 * 60 * 60 * 24);
		return (int) days;
	}

	/**
	 * @param str 获取今天某一时刻的时间戳
	 * @return
	 */
	public static long getRealTimestamp(String str) {
		return getRealTimestamp(System.currentTimeMillis(), 0, str);
	}

	public static long getRealTimestamp(long timestamp, int day, String str) {
		Calendar c = Calendar.getInstance();
		c.setTimeInMillis(timestamp);
		c.add(Calendar.DATE, day);
		try {
			if (StringUtils.isNotBlank(str)) {
				return getDF2().parse(getDF1().format(c.getTimeInMillis()) + " " + str).getTime();
			} else {
				return getZeroTimeStamp(c.getTimeInMillis());
			}
		} catch (ParseException e) {
			e.printStackTrace();
			return 0L;
		}
	}


	/**
	 * 获取本周中某一天的某个时间
	 *
	 * @param dayOfWeekCn 周几
	 * @param str HH:mm:ss
	 * @return
	 */
	public static long getTimeThisWeek(int dayOfWeekCn, String str) {
		Calendar cal = Calendar.getInstance();
		cal.setFirstDayOfWeek(Calendar.MONDAY);
		cal.set(Calendar.DAY_OF_WEEK, TimeKit.dayOfWeekCnToCalendarDay(dayOfWeekCn));
		return getRealTimestamp(cal.getTimeInMillis(), 0, str);
	}

	public static long getNextSundayZeroTime() {
		Calendar c = Calendar.getInstance();
		final int now = c.get(Calendar.DAY_OF_WEEK);
		c.add(Calendar.DAY_OF_WEEK, 8 - now);
		return getZeroTimeStamp(c.getTimeInMillis());
	}

	/**
	 * 两个日期是否为同一天
	 * @param dayTime1
	 * @param dayTime2
	 * @return
	 */
	public static boolean isSameDay(long dayTime1, long dayTime2){
		return !isDifferentDay(dayTime1, dayTime2);
	}

	/**
	 * 两个日期是否为同一天
	 */
	public static boolean isDifferentDay(long dayTime1, long dayTime2) {
		return getDistanceDays(dayTime1, dayTime2) != 0;
	}

	/**
	 * 两个日期是否为同一周(周一为准)
	 */
	public static boolean isDifferentWeek(long time1, long time2) {
		return getZeroMondayTimeStamp(time1) != getZeroMondayTimeStamp(time2);
	}

	/** 获取当周周一零点的时间戳 */
	public static long getZeroMondayTimeStamp(long time) {
		Calendar c = Calendar.getInstance();
		c.setTimeInMillis(time);
		c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);
		return c.getTimeInMillis();
	}

	public static boolean isDayOfWeek(int day) {
		Calendar c = Calendar.getInstance();
		return day == c.get(Calendar.DAY_OF_WEEK);
	}

	/**
	 * 按照中国方式获取的今天是礼拜几
	 */
	public static int dayOfWeekCn(long time) {
		Calendar c = Calendar.getInstance();
		c.setTimeInMillis(time);
		final int d = c.get(Calendar.DAY_OF_WEEK);
		switch (d) {
			case Calendar.MONDAY:
				return 1;
			case Calendar.TUESDAY:
				return 2;
			case Calendar.WEDNESDAY:
				return 3;
			case Calendar.THURSDAY:
				return 4;
			case Calendar.FRIDAY:
				return 5;
			case Calendar.SATURDAY:
				return 6;
			case Calendar.SUNDAY:
				return 7;
		}
		return -1;
	}

	/**
	 * 时间常量
	 */
	public static final class TimeCons {
		/** 秒 */
		public static long SECOND = 1000L;
		/** 分钟 */
		public static long MINUTE = 60 * SECOND;
		/** 小时 */
		public static long HOUR = 60 * MINUTE;
		/** 天 */
		public static long DAY = 24 * HOUR;
		/** 周 */
		public static long WEEK = 7 * DAY;
	}
}
